`timescale	1ps/1ps
module L9_spi_com_01(
		input	wire		resetb,
		input	wire		sclk,
		input	wire		comm_en,

		//和MCU接口	
		input	wire		mcu_spi_cs,
		input	wire		mcu_spi_clk,
		input	wire		mcu_spi_mosi,
		output	reg		mcu_spi_miso,

		input	wire		mcu_fpga_ctrl,

		//和PHY接口	
		output	reg		send_flag,
		output	reg		pre_flag,
		output	reg	[7:0]	send_data,
		
	        //MCU控制输出
	        output	reg		mcu_set_en,
	        
	        output	reg		mcu_set_d_ok,
	        output	reg	[15:0]	mcu_set_addr,
	        output	reg	[7:0]	mcu_set_data,
	        
	        output	reg		mcu_ext_d_ok,
	        output	reg	[15:0]	mcu_ext_addr,
		
	        input	wire	[7:0]	fpga_state,
	        
		//和DMX接口	
		output	reg		mcu_dmx_en,
		output	reg		mcu_dmx_ten,
		output	reg	[7:0]	port_sel,

		//和SD卡接口	
		output	wire		mcu_sd_en,
		output	reg		mcu_sd_rd,

		//和Flash接口	
		output	wire		mcu_flash_en,

		//调试信号
		output	wire	[7:0]	tout
		);

//**********************************************/
//		信号定义
/***********************************************/
wire	[1:0]	logic_mode;

reg		send_buf_wen;
wire	[10:0]	send_buf_raddr;
wire	[13:0]	send_buf_waddr;
wire		send_buf_wdata;
wire	[7:0]	send_buf_rdata;

reg		mcu_spi_cs_a, mcu_spi_mosi_a, mcu_spi_clk_a;
reg		spi_en, spi_bit_in, spi_clk, spi_en_t, spi_clk_t;
reg		spi_bit_sync, spi_bit_end, byte_last_bit, spi_rec_over, spi_rec_end;
reg	[7:0]	spi_bit_sync_t;
reg	[13:0]	spi_rec_count;
wire	[10:0]	spi_byte_count;
reg	[7:0]	ack_shift_d, ack_type;
reg		spi_55_flag, spi_phy_flag, port_config_flag, reg_config_flag;
reg	[10:0]	send_phy_max, send_phy_count;
reg		send_phy_flag, send_phy_last, send_phy_flag_t;

reg		reg_config_en, reg_config_end, ext_flag;
reg	[31:0]	reg_base_addr, reg_cfg_addr;
reg	[8:0]	reg_cfg_length;
reg	[7:0]	reg_cfg_data;

reg		spi_mode_flag;
reg	[1:0]	spi_mode;
	
reg		spi_byte_end, reg_write_flag, reg_read_flag;
reg	[7:0]	mcu_read_data;
reg	[2:0]	spi_bit_sel;

//**********************************************/
//		参数定义
/***********************************************/
//程序版本信息
parameter	main_function	=  "S";		//ASCII "S"  
parameter	sub_function	=  "L";		//ASCII "L"  
parameter	main_solution	=  9;		//"9"        
parameter	sub_solution	=  9;		//"09"       
parameter	application_type=  "G";		//ASCII "G"  
parameter	main_version	=  8'd3;	//"03"       
parameter	sub_version	=  8'd8;	//"X01"  
parameter	mini_version	=  8'd1;	//" "  

`ifdef BOOT_MODE
	assign	logic_mode = 3;
`else
	`ifdef TEST_MODE
		assign	logic_mode = 2;
	`else
		assign	logic_mode = 1;
	`endif
`endif
//parameter	LOGIC_MODE	=	3;	//initial

//*************************************************/
//		数据缓冲
//*************************************************/
L9_swsr_16kw1_2kr8_dp	send_buf(
	.wrclock(sclk),
	.wren(send_buf_wen),
	.wraddress(send_buf_waddr),
	.data(send_buf_wdata),
	
	.rdclock(sclk),
	.rdaddress(send_buf_raddr),
	.q(send_buf_rdata)
	);

//***************缓冲控制***************
//send_buf控制信号
always @(posedge sclk)
	if ((spi_en == 1) && (spi_rec_over == 0))
		send_buf_wen <= spi_bit_sync;
	else
		send_buf_wen <= 0;

assign	send_buf_waddr = {spi_rec_count[13:3], ~spi_rec_count[2:0]};
assign	send_buf_wdata = spi_bit_in;
assign	send_buf_raddr = send_phy_count;

//************************************************/
//		SPI接口处理
//************************************************/
//接口缓冲
always@(posedge sclk) begin
	mcu_spi_cs_a <= ~mcu_spi_cs;
	spi_en <= mcu_spi_cs_a;
	
	mcu_spi_mosi_a <= mcu_spi_mosi;
	spi_bit_in <= mcu_spi_mosi_a;
	
	mcu_spi_clk_a <= mcu_spi_clk;
	spi_clk <= mcu_spi_clk_a;
	end

//信号延迟
always@(posedge sclk) begin
	spi_en_t <= spi_en;
	spi_clk_t <= spi_clk;
	end

//bit数据同步
always@(posedge sclk)
	if ((spi_clk == 1) && (spi_clk_t == 0))
		spi_bit_sync <= 1;
	else
		spi_bit_sync <= 0;
		
//bit数据同步延时
always@(posedge sclk)
	spi_bit_sync_t <= {spi_bit_sync_t[6:0], spi_bit_sync};
	
//bit数据结束
always@(posedge sclk)
	spi_bit_end <= spi_bit_sync_t[3];
	
//接收计数
always@(posedge sclk)
	if (spi_en == 0)
		spi_rec_count <= 14'h00;
	else if ((spi_bit_end == 1) && (spi_rec_over == 0))
		spi_rec_count <= spi_rec_count + 1;
		
//接收长度控制
always@(posedge sclk)
	if (spi_rec_count[13:10] == 4'b1111)
		spi_rec_over <= 1;
	else
		spi_rec_over <= 0;
		
//************************************************/
//		SPI类型处理
//************************************************/
assign	spi_byte_count = spi_rec_count[13:3];

always@(posedge sclk)
	if (spi_bit_sync == 1)
		ack_shift_d <= {ack_shift_d[6:0], spi_bit_in};
	
always@(posedge sclk)
	if ((spi_en == 1) && (spi_rec_end == 0) && (spi_rec_count[2:0] == 3'b111))
		byte_last_bit <= 1;
	else
		byte_last_bit <= 0;
		
always@(posedge sclk)
	if ((spi_bit_sync_t[3] == 1) && (byte_last_bit == 1))
		spi_byte_end <= 1;
	else
		spi_byte_end <= 0;
		
always@(posedge sclk or negedge resetb)
	if(resetb == 0)
		ack_type <= 8'h55;
	else if ((spi_byte_end == 1) && (spi_byte_count == 0))
		ack_type <= ack_shift_d;

always@(posedge sclk)
	if (ack_type == 8'h55)
		spi_55_flag <= 1;
	else
		spi_55_flag <= 0;

always@(posedge sclk)
	if ((spi_byte_end == 1) && (spi_byte_count == 1)) begin
		if ((spi_55_flag == 1) && (ack_shift_d == 8'h55))
			spi_phy_flag <= 1;
		else
			spi_phy_flag <= 0;
		end

always@(posedge sclk)
	if (ack_type == 8'h33)
		port_config_flag <= 1;
	else
		port_config_flag <= 0;

always@(posedge sclk)
	if (ack_type == 8'h5A)
		reg_config_flag <= 1;
	else
		reg_config_flag <= 0;

//************************************************/
//		网口转发处理
//************************************************/
//接收结束标志
always@(posedge sclk)
	if ((spi_en == 0) && (spi_en_t == 1))
		spi_rec_end <= 1;
	else
		spi_rec_end <= 0;
		
//保存转发长度
always@(posedge sclk or negedge resetb)
	if (resetb == 0)
		send_phy_max <= 8;		//初始化非0，防止产生错误的send_phy_last
	else if ((spi_en == 0) && (spi_en_t == 1)) begin
		if (spi_byte_count > 18)
			send_phy_max <= spi_byte_count - 2;
		else
			send_phy_max <= 8;
		end

//PHY转发使能
always@(posedge sclk or negedge resetb)
	if (resetb == 0)
		send_phy_flag <= 0;
	else if ((spi_rec_end == 1) && (spi_phy_flag == 1) && (send_phy_max > 16))
		send_phy_flag <= 1;
	else if (send_phy_last == 1)
		send_phy_flag <= 0;

//PHY转发计数
always@(posedge sclk)
	if (send_phy_flag == 0)
		send_phy_count <= 0;
	else
		send_phy_count <= send_phy_count + 1;

//PHY转发结束
always@(posedge sclk)
	if ((send_phy_flag == 1) && (send_phy_count >= send_phy_max))
		send_phy_last <= 1;
	else
		send_phy_last <= 0;

//***************输出给PHY的信号***************
//MCU应答信号
always@(posedge sclk) begin
	send_phy_flag_t <= send_phy_flag;
	send_flag <= send_phy_flag_t;
	end

always@(posedge sclk)
	if (send_phy_count > 0 && send_phy_count < 9)
		pre_flag <= 1;
	else
		pre_flag <= 0;

always@(posedge sclk)
	if (send_phy_flag_t == 1)
		send_data <= send_buf_rdata;
	else
		send_data <= 0;

//************************************************/
//		端口配置处理
//************************************************/
always@(posedge sclk or negedge resetb)
	if(resetb == 0) begin
		port_sel <= 0;
		mcu_dmx_en <= 0;
		end
	else if ((spi_byte_end == 1) && (port_config_flag == 1))
		case (spi_byte_count)
			2:	port_sel <= ack_shift_d;
			3:	mcu_dmx_en <= ack_shift_d[0];
		endcase

always @( * )
	if ((mcu_sd_en == 0) && (mcu_dmx_en == 1))
		mcu_dmx_ten <= mcu_fpga_ctrl;
	else
		mcu_dmx_ten <= 1;

//************************************************/
//		SD卡处理
//************************************************/
/*
always@(posedge sclk or negedge resetb)
	if(resetb == 0)
		mcu_sd_flag <= 0;
	else if ((spi_en == 1) && (spi_en_t == 0))
		mcu_sd_flag <= 1;
	else if (spi_byte_end == 1)
		case (spi_byte_count)
			0:	if (ack_shift_d != 8'hFF)
					mcu_sd_flag <= 0;
			1:	if (ack_shift_d != 8'hFF)
					mcu_sd_flag <= 0;
			2:	if (ack_shift_d != 8'hFF)
					mcu_sd_flag <= 0;
			3:	if (ack_shift_d != 8'hFF)
					mcu_sd_flag <= 0;
			4:	if (ack_shift_d != 8'h5A)
					mcu_sd_flag <= 0;
			5:	if (ack_shift_d != 8'hA5)
					mcu_sd_flag <= 0;
			6:	if (ack_shift_d != 8'h53)
					mcu_sd_flag <= 0;
		endcase
*/
always@(posedge sclk or negedge resetb)
	if(resetb == 0)
		spi_mode_flag <= 0;
	else if ((spi_en == 1) && (spi_en_t == 0))
		spi_mode_flag <= 1;
	else if (spi_byte_end == 1)
		case (spi_byte_count)
			0:	if (ack_shift_d != 8'h55)
					spi_mode_flag <= 0;
			1:	if (ack_shift_d != 8'h3A)
					spi_mode_flag <= 0;
			2:	if (ack_shift_d != 8'hFF)
					spi_mode_flag <= 0;
			3:	if (ack_shift_d != 8'hFF)
					spi_mode_flag <= 0;
			4:	if (ack_shift_d != 8'h5A)
					spi_mode_flag <= 0;
			5:	if (ack_shift_d != 8'hA5)
					spi_mode_flag <= 0;
			//6:	if (ack_shift_d != 8'h53)//删除
			//		spi_mode_flag <= 0;
		endcase

always@(posedge sclk or negedge resetb)
	if(resetb == 0)
		spi_mode <= 0;
	else if ((spi_byte_end == 1) && (spi_byte_count == 6) && (spi_mode_flag == 1))
	//else if ((spi_byte_end == 1) && (spi_byte_count == 7) && (spi_mode_flag == 1))
		case (ack_shift_d)
			8'h35:	spi_mode <= 1;
			8'hAD:	spi_mode <= 2;
			default:	spi_mode <= 0;
		endcase

assign	mcu_sd_en = spi_mode[0];
assign	mcu_flash_en = spi_mode[1];

always@(posedge sclk)
	if (mcu_sd_en == 1)
		mcu_sd_rd <= mcu_fpga_ctrl;
	else
		mcu_sd_rd <= 0;

//************************************************/
//		参数设置处理
//************************************************/
//寄存器写标志
always@(posedge sclk or negedge resetb)
	if(resetb == 0)
		reg_write_flag <= 0;
	else if ((spi_byte_end == 1) && (spi_byte_count == 1) && (reg_config_flag == 1)) begin
		if (ack_shift_d == 8'h00)
			reg_write_flag <= 1;
		else
			reg_write_flag <= 0;
		end

always@(posedge sclk or negedge resetb)
	if(resetb == 0) begin
		reg_base_addr <= 0;
		reg_cfg_length <= 0;
		end
	else if ((spi_byte_end == 1) && (reg_config_flag == 1))
		case (spi_byte_count)
			2:	reg_base_addr[7:0] <= ack_shift_d;
			3:	reg_base_addr[15:8] <= ack_shift_d;
			4:	reg_base_addr[23:16] <= ack_shift_d;
			5:	reg_base_addr[31:24] <= ack_shift_d;
			6:	reg_cfg_length[7:0] <= ack_shift_d;
			7:	reg_cfg_length[8] <= ack_shift_d[0];
		endcase

always@(posedge sclk)
	if (spi_byte_count >= (reg_cfg_length + 8))
		reg_config_end <= 1;
	else
		reg_config_end <= 0;
		
always@(posedge sclk or negedge resetb)
	if(resetb == 0)
		reg_config_en <= 0;
	else if ((spi_en == 0) || (spi_rec_over == 1))
		reg_config_en <= 0;
	else if (spi_byte_end == 1) begin
		if ((spi_byte_count == 8) && (reg_config_flag == 1))
			reg_config_en <= 1;
		else if (reg_config_end == 1)
			reg_config_en <= 0;
		end

always@(posedge sclk or negedge resetb)
	if(resetb == 0) begin
		reg_cfg_addr <= 0;
		reg_cfg_data <= 0;
		end
	else if ((spi_byte_end == 1) && (reg_config_flag == 1)) begin
		reg_cfg_addr <= reg_base_addr +  spi_byte_count - 8;
		reg_cfg_data <= ack_shift_d;
		end
	
always@( * ) begin
	mcu_set_addr <= reg_cfg_addr[15:0];
	mcu_ext_addr <= reg_cfg_addr[31:16];
	mcu_set_data <= reg_cfg_data;
	end

always@(posedge sclk)
	if (mcu_ext_addr == 16'h0)
		ext_flag <= 0;
	else
		ext_flag <= 1;

reg		w_d_ok;
reg	[7:0]	w_d_ok_t;

always@(posedge sclk)
	if ((reg_write_flag == 1) && (spi_byte_end == 1) && (spi_byte_count > 7))
		w_d_ok <= 1;
	else
		w_d_ok <= 0;
		
always@(posedge sclk)
	w_d_ok_t <= {w_d_ok_t, w_d_ok};
		
always@(posedge sclk)
	if ((w_d_ok_t == 1) && (ext_flag == 0))
		mcu_set_d_ok <= 1;
	else
		mcu_set_d_ok <= 0;
		
always@(posedge sclk)
	if ((w_d_ok_t == 1) && (ext_flag == 1))
		mcu_ext_d_ok <= 1;
	else
		mcu_ext_d_ok <= 0;
	
always@( * ) 
	mcu_set_en <= reg_config_en;

//***********************************************/
//		参数读取处理
//***********************************************/
//寄存器读标志
always@(posedge sclk or negedge resetb)
	if(resetb == 0)
		reg_read_flag <= 0;
	else if ((spi_byte_end == 1) && (spi_byte_count == 1) && (reg_config_flag == 1)) begin
		if (ack_shift_d == 8'h33)
			reg_read_flag <= 1;
		else
			reg_read_flag <= 0;
		end

//返回数据
always@(posedge sclk)
	if (reg_read_flag == 0)
		mcu_read_data <= 0;
	else if (spi_byte_count < 8)
		mcu_read_data <= 0;
	else	
		case (mcu_set_addr[7:0])
			8'h00:	mcu_read_data <= fpga_state[0];//fpga_state
			//8'h01:	mcu_read_data <= port_sel;
			
			8'h10:	mcu_read_data <= main_function;
			8'h11:	mcu_read_data <= sub_function;
			8'h12:	mcu_read_data <= main_solution;
			8'h13:	mcu_read_data <= sub_solution;
			8'h14:	mcu_read_data <= application_type;
			8'h15:	mcu_read_data <= main_version;
			8'h16:	mcu_read_data <= sub_version;
			8'h17:	mcu_read_data <= mini_version;
			
			8'h20:	mcu_read_data <= logic_mode;
			default:	mcu_read_data <= 0;
		endcase
		
//返回数据bit选择
always@(posedge sclk)
	spi_bit_sel <= ~spi_rec_count;
	
//返回数据
always@(posedge sclk)
	mcu_spi_miso <= mcu_read_data[spi_bit_sel];

/************************************************/
//		测试信号
/************************************************/
assign	tout = {spi_en, spi_bit_in, spi_clk, spi_bit_sync, spi_bit_end, byte_last_bit, spi_byte_count[0], spi_mode_flag};

endmodule		
